package com.nathan.crm.service;

import com.nathan.base.BaseService;
import com.nathan.crm.dao.ModuleMapper;
import com.nathan.crm.dao.PermissionMapper;
import com.nathan.crm.dao.RoleMapper;
import com.nathan.crm.utils.AssertUtil;
import com.nathan.crm.vo.Module;
import com.nathan.crm.vo.Permission;
import com.nathan.crm.vo.Role;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class RoleService extends BaseService<Role,Integer> {

    @Resource
    private RoleMapper roleMapper;
    @Resource
    private PermissionMapper permissionMapper;
    @Resource
    private ModuleMapper moduleMapper;

    /**
     * 查询所有角色的id和角色名
     * @return
     */
    public List<Map<String,Object>> queryAllRoles(Integer userId){
        return roleMapper.queryAllRoles(userId);
    }

    /**
     * 添加角色
     *      1、参数校验
     *          角色名     非空、惟一
     *          角色备注    非空
     *      2、设置默认值
     *          is_valid    1
     *          创建时间    当前时间
     *          更新时间    当前时间
     *      3、执行添加操作
     * @param role
     */
    @Transactional
    public void addRole(Role role){
        /* 1、参数校验 */
        checkRoleParams(role.getRoleName(),role.getRoleRemark(),role.getId());

        /* 2、设置默认值 */
        role.setCreateDate(new Date());
        role.setUpdateDate(new Date());
        role.setIsValid(1);

        /* 执行添加操作 */
        AssertUtil.isTrue(roleMapper.insertSelective(role) != 1,"角色添加失败！");
    }

    /**
     * 参数校验
     * @param roleName
     * @param roleRemark
     * @param roleId
     */
    private void checkRoleParams(String roleName, String roleRemark,Integer roleId) {
        // 角色名     非空、惟一
        AssertUtil.isTrue(StringUtils.isBlank(roleName),"请输入角色名！");
        Role role = roleMapper.selectByRoleName(roleName);
        // 如果是更新操作，如果角色存在，还需要判断更新的角色id和查询到的角色id是否一致，不一致表示角色名被占用
        AssertUtil.isTrue(role != null && !(role.getId().equals(roleId)),"角色已存在,请重新输入！");
        // 角色备注    非空
        AssertUtil.isTrue(StringUtils.isBlank(roleRemark),"角色备注不能为空！");
    }

    /**
     * 更新角色
     * @param role
     */
    @Transactional
    public void updateRole(Role role) {
        /* 参数校验 */
        // 判断角色id是否为空
        AssertUtil.isTrue(null == role.getId(),"角色信息不存在,请重试！");
        checkRoleParams(role.getRoleName(),role.getRoleRemark(),role.getId());

        /* 执行更新操作 */
        AssertUtil.isTrue(roleMapper.updateByPrimaryKeySelective(role) != 1,"更新失败！");
    }

    /**
     * 根据角色id删除角色
     * @param id
     */
    @Transactional
    public void deleteRoleById(Integer id) {
        /* 参数校验 */
        // id非空
        AssertUtil.isTrue(null == id,"角色信息不存在！");
        // id对应的角色数据存在
        Role role = roleMapper.selectByPrimaryKey(id);
        AssertUtil.isTrue(null == role,"角色信息不存在！");

        // 设置默认值
        role.setIsValid(0);

        // 执行更新操作
        roleMapper.updateByPrimaryKeySelective(role);
    }

    /**
     * 角色授权
     *      将对应的角色ID与资源ID,添加到对应的权限表中
     *          直接添加权限:不合适，会出现重复的权限数据（执行修改权限操作后删除权限操作时)
     *          推荐使用:
     *              先将已有的权限记录删除,再将需要设置的权限记录添加
     *          1、通过角色ID查询对应的权限记录
     *          2、如果权限记录存在，则删除对应的角色拥有的权限记录
     *          3、如果有权限记录，则添加权限记录
     *
     * @param mids
     * @param roleId
     */
    @Transactional
    public void addGrand(Integer[] mids, Integer roleId) {
        /* 1、通过角色ID查询对应的权限记录 */
        Integer count = permissionMapper.countPermissionByRoleId(roleId);

        // 角色id对应的权限记录存在，删除对应的记录
        if (count > 0){
            permissionMapper.deletePermissionByRoleId(roleId);
        }

        // 如果有权限记录，则添加权限记录
        if (null != mids && mids.length > 0){
            // 批量添加，先创建权限集合
            List<Permission> permissionList = new ArrayList<>();
            // 遍历mids
            for (Integer mid : mids){
                Permission permission = new Permission();
                permission.setRoleId(roleId);
                permission.setModuleId(mid);
                permission.setAclValue(moduleMapper.selectByPrimaryKey(mid).getOptValue());

                permissionList.add(permission);
            }
            AssertUtil.isTrue(permissionMapper.insertBatch(permissionList) != permissionList.size(),"角色授权失败！");
        }

    }
}
